namespace OpenComposite.SOBADesigner
{
	using System;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Data;
	using System.Drawing;
	using System.Windows.Forms;

	using OpenComposite.EII;
	using OpenComposite.EII.Repository;
	using OpenComposite.EII.Services;

	using OpenComposite.Base;

	internal partial class UCComponentTree : UserControl, OpenComposite.EII.IRepositoryExplorerTree
	{
		#region Initialization

		public UCComponentTree(IServiceProvider serviceProvider)
		{
			this.ItemSelected = null;
			this.DeleteItem = null;
			this.CreateProcessForMethod = null;
			this.AddDiagram = null;
			this.OpenDiagram = null;

			_serviceProvider = serviceProvider;

			InitializeComponent();

			this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
			this.SetStyle(ControlStyles.ResizeRedraw, false);
			this.UpdateStyles();

			_changeService = _serviceProvider.GetService(typeof(IRepositoryChangeService)) as IRepositoryChangeService;
			if ( _changeService == null )
				throw new NullReferenceException("IRepositoryChangeService not available.");

			_changeService.RepositoryAdded += new RepositoryEventHandler(_changeService_RepositoryAdded);
			_changeService.RepositoryChanged += new RepositoryChangedEventHandler(_changeService_RepositoryChanged);
			_changeService.RepositoryRemoved += new RepositoryEventHandler(_changeService_RepositoryRemoved);

#if !DEBUG
			miTIAddChildDocumentation.Visible = false;
#endif
		}

		#endregion Initialization

		#region Public Members

		#region Constant/Read-Only Fields

		public const int AllDomainsID = -1;

		#endregion Constant/Read-Only Fields

		#region Events

		public event EventHandler<ItemSelectedEventArgs> AddDiagram;

		public event EventHandler<ItemSelectedEventArgs> CreateProcessForMethod;

		public event EventHandler<ItemSelectedEventArgs> DeleteItem;

		public event EventHandler<ItemSelectedEventArgs> ItemSelected;

		public event EventHandler<ItemSelectedEventArgs> OpenDiagram;

		#endregion Events

		#region Properties

		public int CurrentDomainID
		{
			get { return _idDomain; }
			set
			{
				if ( _idDomain != value ) {
					_idDomain = value;
					loadRepository();
				}
			}
		}

		public int CurrentRepositoryID
		{
			get { return _idRepository; }
			set
			{
				if ( _idRepository != value ) {
					_idRepository = value;
					doRepositoryChanged();
				}
			}
		}

		public TreeType CurrentTreeType
		{
			get { return _type; }
			set
			{
				if ( _type != value ) {
					_type = value;
					doTreeTypeChanged();
				}
			}
		}

		public ItemType CurrentViewType
		{
			get { return _typeView; }
			set
			{
				if ( _typeView != value ) {
					_typeView = value;
					if ( !this.DesignMode )
						loadRepository();
				}
			}
		}

		public RepositoryService Repository
		{
			get { return (RepositoryService)GetService(typeof(RepositoryService)); }
		}

		public bool SelectDomainVisible
		{
			get { return tsbtnDomain.Visible; }
			set
			{
				tsbtnDomain.Visible = value;
				tssepDomain.Visible = value;
			}
		}

		public bool SelectViewVisible
		{
			get { return tsbtnViews.Visible; }
			set
			{
				tsbtnViews.Visible = value;
				tssepView.Visible = value;
			}
		}

		public bool ToolStripVisible
		{
			get { return tsMain.Visible; }
			set { tsMain.Visible = value; }
		}

		public TreeViewEx TreeView
		{
			get { return this.treeRepository; }
		}

		[Browsable(false)]
		public ItemType[] VisibleItemTypes
		{
			get { return _listVisibleTypes.ToArray(); }
			set
			{
				_listVisibleTypes.Clear();
				if ( value != null && value.Length > 0 )
					_listVisibleTypes.AddRange(value);
				loadRepository();
			}
		}

		#endregion Properties

		#region Methods

		public TreeNode FindTreeNode(IRepositoryItem item)
		{
			RepositoryItemBaseEx itemEx = item as RepositoryItemBaseEx;
			//if ( itemEx == null ) return null;

			// first chance
			List<TreeNode> nodes = findNodesOfRepositoryItem(item);
			if ( nodes.Count > 0 ) {
				return nodes[nodes.Count - 1];
			}

			List<DataRow> rows = new List<DataRow>();
			int id = item.ID;
			int type = (int)item.RepositoryItemType;
			while ( id > 0 ) {
				DataRow[] dtRows = _dtRepository.Select(string.Format("child_id = {0} AND child_reptype_id = {1}",
																	id, (int)type));
				if ( dtRows.Length > 0 ) {
					DataRow cRow = dtRows[dtRows.Length - 1];
					if ( cRow["parent_id"] == DBNull.Value ) break;
					id = (int)cRow["parent_id"];
					type = (int)cRow["parent_reptype_id"];
					rows.Add(cRow);
				} else {
					return null;
				}
			}
			Domain domain;
			if ( itemEx != null ) {
				domain = Repository.GetItem<Domain>(itemEx.DomainId);
			} else {
				domain = Repository.GetItem<Domain>(Global.Status.CurrentDomainId);
			}
			List<TreeNode> domains = findNodesOfRepositoryItem(domain);
			if ( domains == null || domains.Count < 1 ) return null;
			TreeNode domainNode = domains[0];
			domainNode.Expand();
			TreeNode returnValue = domainNode;
			string key = null;
			string keyCurrent = "";
			for ( int i = rows.Count - 1; i >= 0; i-- ) {
				DataRow current = rows[i];
				if ( i == rows.Count - 1 ) {
					key = string.Format(".{0}${1}$.{2}${3}$", current["parent_reptype_id"], current["parent_id"],
							current["child_reptype_id"], current["child_id"]);
				} else {
					keyCurrent = string.Format(".{0}${1}$", current["child_reptype_id"], current["child_id"]);
				}
				foreach ( TreeNode node in returnValue.Nodes ) {
					if ( node.Name == key + keyCurrent ) {
						node.Expand();
						returnValue = node;
						key += keyCurrent;
						break;
					}
				}
			}

			//if ( nodes.Count > 0 ) {
			//    TreeNode domainNode = nodes[0];
			//    domainNode.TreeView.BeginUpdate();
			//    domainNode.ExpandAll();
			//    domainNode.Collapse(false);
			//    domainNode.TreeView.EndUpdate();
			//}

			//nodes = findNodesOfRepositoryItem(item);

			return returnValue;
		}

		public bool SelectRepositoryItem(IRepositoryItem item)
		{
			return this.SelectRepositoryItem(item, true);
		}

		public bool SelectRepositoryItem(IRepositoryItem item, bool activate)
		{
			bool isItemSelected = false;
			TreeNode tn = FindTreeNode(item);
			if ( tn != null ) {
				this.TreeView.SelectedNode = tn;
				if ( activate ) {
					onItemSelected(item.RepositoryItemType, tn);
				}
				isItemSelected = true;
			}
			return isItemSelected;
		}

		public void UpdateRepository()
		{
			loadRepository();
		}

		public void UpdateSubTree(IRepositoryItem item)
		{
			treeRepository.BeginUpdate();
			List<TreeNode> lstNodes = findNodesOfRepositoryItem(item);
			if ( lstNodes != null && lstNodes.Count > 0 ) {
				_dtRepository = Global.Data.GetRepositoryHierarchy(_idRepository);
				foreach ( var tn in lstNodes ) {
					string key = tn.Name;
					IRepositoryItem ri = tn.Tag as IRepositoryItem;
					tn.Nodes.Clear();
					addTreeChildNodes(_dtRepository, tn.Nodes, key, ri);
				}
			}
			treeRepository.EndUpdate();
		}

		#endregion Methods

		#endregion Public Members

		#region Protected Members

		#region Methods

		protected override object GetService(Type service)
		{
			return _serviceProvider.GetService(service);
		}

		#endregion Methods

		#endregion Protected Members

		#region Private Members

		#region Constant/Read-Only Fields

		private const string _LOADING = "...Loading";

		#endregion Constant/Read-Only Fields

		#region Fields

		private BitmapCursor _bmpcurDrag = null;
		private IRepositoryChangeService _changeService;
		private DataTable _dtRepository;
		private int _idDomain = AllDomainsID;
		private int _idRepository = -1;
		private volatile bool _isInAddNew = false;
		private List<ItemType> _listVisibleTypes = new List<ItemType>();
		private string _selectedPath = "";
		private IServiceProvider _serviceProvider;
		private TreeNode _tnDrag = null;
		private TreeType _type = TreeType.DomainEditor;
		private ItemType _typeView = ItemType.Domain;

		#endregion Fields

		#region Event Handlers

		private void _changeService_RepositoryAdded(object sender, RepositoryEventArgs e)
		{
		}

		private void _changeService_RepositoryChanged(object sender, RepositoryChangedEventArgs e)
		{
			if ( e.Member == null ) return;
			try {
				if ( treeRepository.IsDisposed ) return;

				string newValue = e.NewValue != null ? e.NewValue.ToString() : "";
				if ( e.Member.Name == "Name" && e.RepositoryItem != null ) {
					List<TreeNode> lstNodes = findNodesOfRepositoryItem(e.RepositoryItem);
					foreach ( var tn in lstNodes ) {
						tn.Text = e.RepositoryItem.Display;
					}
				} else if ( ( e.Member.Name == "AddRepositoryHierarchy" && newValue == "Parent" ) ||
							( e.Member.Name == "DeleteRepositoryHierarchy" && newValue == "Parent" ) ) {
					if ( !_isInAddNew && e.RepositoryItem != null ) {
						UpdateSubTree(e.RepositoryItem);
					}
				} else if ( e.Member.Name == "DeleteRepositoryHierarchy" && newValue == "All" ) {
					WorkflowField field = e.RepositoryItem as WorkflowField;
					if ( field != null ) {
						if ( field.Workflow == null ) {
							TreeNode node = FindTreeNode(field);
							IRepositoryItem item = node.Parent.Tag as IRepositoryItem;
							if ( item != null ) {
								UpdateSubTree(item);
							}
						}
					} else {
						loadRepository();
					}
				} else if ( e.Member.Name == "Save" && e.NewValue is RepositoryItemBase ) {
					//this.UpdateSubTree(e.NewValue as IRepositoryItem);
					//TreeNode tn = FindTreeNode(e.NewValue as IRepositoryItem);
					//if ( tn == null ) {
					//}
					//List<TreeNode> nodes = this.findNodesOfRepositoryItem(itemEx);
					//Domain domain = Global.Data.RepositoryService.GetItem<Domain>(itemEx.DomainId);
					//TreeNode domainNode = FindTreeNode(domain);
					//TreeNode toUpdate = findTreeNodeByText(domainNode.Nodes, "Business Objects");
					//if ( toUpdate != null ) {
					//    this.UpdateSubTree(toUpdate as IRepositoryItem);
					//}
				}
			} catch { }
		}

		private void _changeService_RepositoryRemoved(object sender, RepositoryEventArgs e)
		{
		}

		private void miTIAddBRuleDiagram_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Diagram, ItemType.BRule, false);
		}

		private void miTIAddChildAPIService_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.APIService, false);
		}

		private void miTIAddChildBObject_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.BObject, false);
		}

		private void miTIAddChildBPolicy_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.BPolicy, false);
		}

		private void miTIAddChildBProcess_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Business_Process, false);
		}

		private void miTIAddChildCapability_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Capability, false);
		}

		private void miTIAddChildComponent_Click(object sender, EventArgs e)
		{
			ItemType type = ItemType.Component;
			if ( sender == miTIAddChildHumanComponent )
				type = ItemType.HumanComponent;
			else if ( sender == miTIAddChildSQLComponent )
				type = ItemType.SQLComponent;
			addNewNodeToCurrentTree(type, false);
		}

		private void miTIAddChildComposite_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Composite, false);
		}

		private void miTIAddChildDocumentation_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Documentation, false);
		}

		private void miTIAddChildDomain_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Domain, false);
		}

		private void miTIAddChildFolder_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.GenericFolder, false);
		}

		private void miTIAddChildHAForm_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.HumanActivity, false);
		}

		private void miTIAddChildLogMethodGroup_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.LogicalMethodGroup, false);
		}

		private void miTIAddChildLogMethod_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.LogicalWebMethod, false);
		}

		private void miTIAddChildMashup_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Mashup, false);
		}

		private void miTIAddChildMessageQueue_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.MessageQueue, false);
		}

		private void miTIAddChildNoun_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Noun, false);
		}

		private void miTIAddChildOperation_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Operation, false);
		}

		private void miTIAddChildRuleConstant_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.RuleConstant, false);
		}

		private void miTIAddChildSystem_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.System, false);
		}

		private void miTIAddChildUIComponent_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.UIComponent, false);
		}

		private void miTIAddChildVerb_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Verb, false);
		}

		private void miTIAddChildWebService_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.WebService, false);
		}

		private void miTIAddChildWorkflow_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Workflow, false);
		}

		private void miTIAddConnectionDiagram_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Diagram, ItemType.Diagram, false);
		}

		private void miTIAddDiagramBO_Click(object sender, EventArgs e)
		{
			if ( this.AddDiagram != null )
				this.AddDiagram(this, new ItemSelectedEventArgs(ItemType.BObject, null, _idRepository));
		}

		private void miTIAddFASvcDiagram_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Diagram, ItemType.FA_View, false);
		}

		private void miTIAddITStructDiagram_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Diagram, ItemType.ITObject, false);
		}

		private void miTIAddOrg_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Organization, false);
		}

		private void miTIAddRootBObject_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.BObject, true);
		}

		private void miTIAddRootBPolicy_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.BPolicy, true);
		}

		private void miTIAddRootDomain_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Domain, true);
		}

		private void miTIAddRootFolder_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.GenericFolder, true);
		}

		private void miTIAddRootNoun_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Noun, true);
		}

		private void miTIAddRootOperation_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Operation, true);
		}

		private void miTIAddRootService_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Component, true);
		}

		private void miTIAddRootSvcModule_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Composite, true);
		}

		private void miTIAddRootVerb_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.Verb, true);
		}

		private void miTIAddSOBA_Click(object sender, EventArgs e)
		{
			addNewNodeToCurrentTree(ItemType.SOBA, false);
		}

		private void miTICollapseAll_Click(object sender, EventArgs e)
		{
			if ( treeRepository.SelectedNode != null ) {
				treeRepository.BeginUpdate();
				treeRepository.SelectedNode.Collapse(false);
				treeRepository.EndUpdate();
			}
		}

		private void miTICreateCopy_Click(object sender, EventArgs e)
		{
			if ( this.TopLevelControl != null ) this.TopLevelControl.Refresh();
			if ( treeRepository.SelectedNode == null ) return;

			TreeNode selectedNode = treeRepository.SelectedNode;
			TreeNode parentNode = selectedNode.Parent;
			IRepositoryItem item = selectedNode.Tag as IRepositoryItem;
			IRepositoryItem copy = item.Copy(true);
			if ( parentNode != null ) {
				IRepositoryItem parentItem = parentNode.Tag as IRepositoryItem;
				if ( parentItem == null ) return;
				Global.Data.AddRepositoryHierarchy(parentItem, copy, Global.Status.CurrentRepositoryId);
				this.UpdateSubTree(parentItem);
			}
		}

		private void miTIDelete_Click(object sender, EventArgs e)
		{
			deleteCurrentSelectedNode();
		}

		private void miTIExpandAll_Click(object sender, EventArgs e)
		{
			if ( treeRepository.SelectedNode != null ) {
				treeRepository.BeginUpdate();
				treeRepository.SelectedNode.ExpandAll();
				treeRepository.EndUpdate();
			}
		}

		private void miTIOpenDiagram_Click(object sender, EventArgs e)
		{
			openDiagramOfCurrentNode();
		}

		private void miTIRefresh_Click(object sender, EventArgs e)
		{
			loadRepository();
		}

		private void treeRepository_AfterSelect(object sender, TreeViewEventArgs e)
		{
			// CHANGE: use NodeMouseClick to click on the selected item to get the details
		}

		private void treeRepository_BeforeExpand(object sender, TreeViewCancelEventArgs e)
		{
			if ( e.Node.FirstNode.Text == _LOADING ) {
				string key = e.Node.Name;
				IRepositoryItem item = e.Node.Tag as IRepositoryItem;
				e.Node.FirstNode.Remove();
				addTreeChildNodes(_dtRepository, e.Node.Nodes, key, item);
			}
		}

		private void treeRepository_DragDrop(object sender, DragEventArgs e)
		{
			treeRepository.SuspendLayout();
			treeRepository.BeginUpdate();
			try {
				TreeNode tnSource = e.Data.GetData(typeof(TreeNode)) as TreeNode;
				TreeViewHitTestInfo tvhti = treeRepository.HitTest(treeRepository.PointToClient(new Point(e.X, e.Y)));
				if ( tvhti.Node == null ) return;
				Domain domain = getParentDomainTreeNode(tvhti.Node).Tag as Domain;
				RepositoryItemBase itemSource = tnSource.Tag as RepositoryItemBase;
				RepositoryItemBase itemTarget = tvhti.Node.Tag as RepositoryItemBase;
				if ( itemTarget == null || itemSource == null || itemSource == itemTarget )
					return;
				//GenericFolder folder = itemTarget as GenericFolder;
				ItemType typeSource = itemSource.RepositoryItemType;
				if ( typeSource == ItemType.Workflow ) {
					OpenComposite.EII.Repository.Workflow wf = itemSource as OpenComposite.EII.Repository.Workflow;
					if ( wf != null ) {
						switch ( wf.Type ) {
							case WorkflowType.Business_Process:
								if ( itemTarget.AllowedChildTypes.Contains(ItemType.Business_Process) )
									typeSource = ItemType.Business_Process;
								break;
							case WorkflowType.Orchestration:
								if ( itemTarget.AllowedChildTypes.Contains(ItemType.Workflow) )
									typeSource = ItemType.Workflow;
								break;
							case WorkflowType.Mashup:
							case WorkflowType.Mashup_Horizontal:
								typeSource = ItemType.Mashup;
								break;
						}
					}
				}
				// if ( folder != null && folder.AllowedChildTypes.Contains(typeSource) ) {
				bool isSameTypesFolder = false;
				if ( itemSource.RepositoryItemType == ItemType.GenericFolder &&
					 itemTarget.RepositoryItemType == ItemType.GenericFolder ) {
					if ( itemTarget.AllowedChildTypes.Count == itemSource.AllowedChildTypes.Count ) {
						isSameTypesFolder = true;
						foreach ( var item in itemSource.AllowedChildTypes ) {
							isSameTypesFolder = itemTarget.AllowedChildTypes.Contains(item);
							if ( !isSameTypesFolder ) break;
						}
					} else {
						isSameTypesFolder = false;
					}
				}
				if ( ( itemTarget.AllowDrop && itemTarget.AllowedChildTypes.Contains(typeSource) ) ||
					 isSameTypesFolder ) {
					// move item to another folder
					if ( tnSource.Parent == null ) return;
					RepositoryItemBase itemSourceParent = tnSource.Parent.Tag as RepositoryItemBase;
					if ( itemSourceParent == null ) return;
					Global.Data.DeleteRepositoryHierarchy(itemSourceParent, itemSource, Global.Status.CurrentRepositoryId);
					tnSource.Remove();
					//tvhti.Node.Nodes.Add(tnSource);
					if ( !tvhti.Node.IsExpanded ) tvhti.Node.Expand();
					if ( typeSource == ItemType.Workflow || typeSource == ItemType.Business_Process ) {
						OpenComposite.EII.Repository.Workflow wf = itemSource as OpenComposite.EII.Repository.Workflow;
						if ( wf != null ) {
							if ( itemTarget.AllowedChildTypes.Contains(ItemType.Business_Process) ) {
								wf.Type = WorkflowType.Business_Process;
								wf.Save();
							} else if ( itemTarget.AllowedChildTypes.Contains(ItemType.Workflow) ) {
								wf.Type = WorkflowType.Orchestration;
								wf.Save();
							}
							//tnSource.ImageKey = wf.ImageKey;
							//tnSource.SelectedImageKey = wf.SelectedImageKey;
						}
					}
					RepositoryItemBaseEx itemEx = itemSource as RepositoryItemBaseEx;
					if ( itemEx != null ) itemEx.DomainId = domain.ID;
					itemEx.Save();
					Global.Data.AddRepositoryHierarchy(itemTarget, itemSource, Global.Status.CurrentRepositoryId);
				} else if ( itemTarget.RepositoryItemType == ItemType.BObject &&
					 ( itemSource.RepositoryItemType == ItemType.Noun /*|| itemSource.RepositoryItemType == ItemType.NounCategory*/ ) ) {
					addNounsToBObject(tvhti.Node, tnSource);
					tvhti.Node.Expand();
				} else if ( itemTarget.RepositoryItemType == ItemType.BObject && itemSource.RepositoryItemType == ItemType.BObject ) {
					addBObjectToBObject(tvhti.Node, tnSource);
					tvhti.Node.Expand();
				}
			} finally {
				treeRepository.EndUpdate();
				treeRepository.ResumeLayout(true);
			}
		}

		private void treeRepository_DragEnter(object sender, DragEventArgs e)
		{
		}

		private void treeRepository_DragLeave(object sender, EventArgs e)
		{
		}

		private void treeRepository_DragOver(object sender, DragEventArgs e)
		{
			e.Effect = DragDropEffects.None;

			TreeNode tnSource = e.Data.GetData(typeof(TreeNode)) as TreeNode;
			if ( tnSource == null )
				return;
			TreeViewHitTestInfo tvhti = treeRepository.HitTest(treeRepository.PointToClient(new Point(e.X, e.Y)));
			if ( tvhti.Node == null )
				return;
			RepositoryItemBase itemTarget = tvhti.Node.Tag as RepositoryItemBase;
			RepositoryItemBase itemSource = tnSource.Tag as RepositoryItemBase;
			if ( itemTarget == null || itemSource == null || itemSource == itemTarget )
				return;

			//GenericFolder folder = item as GenericFolder;
			ItemType typeSource = itemSource.RepositoryItemType;
			if ( typeSource == ItemType.Workflow ) {
				OpenComposite.EII.Repository.Workflow wf = itemSource as OpenComposite.EII.Repository.Workflow;
				if ( wf != null ) {
					switch ( wf.Type ) {
						case WorkflowType.Business_Process:
							if ( itemTarget.AllowDrop && itemTarget.AllowedChildTypes.Contains(ItemType.Business_Process) )
								typeSource = ItemType.Business_Process;
							break;
						case WorkflowType.Orchestration:
							if ( itemTarget.AllowDrop && itemTarget.AllowedChildTypes.Contains(ItemType.Workflow) )
								typeSource = ItemType.Workflow;
							break;
						case WorkflowType.Mashup:
						case WorkflowType.Mashup_Horizontal:
							typeSource = ItemType.Mashup;
							break;
					}
				}
			}
			if ( itemSource.RepositoryItemType == ItemType.GenericFolder &&
				 itemTarget.RepositoryItemType == ItemType.GenericFolder ) {
				bool isSameTypes = true;
				foreach ( var item in itemSource.AllowedChildTypes ) {
					isSameTypes = itemTarget.AllowedChildTypes.Contains(item);
					if ( !isSameTypes ) break;
				}
				e.Effect = isSameTypes ? DragDropEffects.Move : DragDropEffects.None;
			} else if ( itemTarget.AllowDrop && itemTarget.AllowedChildTypes.Contains(typeSource) ) {
				// move item to another folder
				e.Effect = DragDropEffects.Move;
			}
			//if ( item.RepositoryItemType == ItemType.BObject &&
			//     ( ( itemSource.RepositoryItemType == ItemType.BObject && itemSource.ID != item.ID /*&& item.ParentBObjectID == -1*/ ) ||
			//       itemSource.RepositoryItemType == ItemType.Noun ||
			//       itemSource.RepositoryItemType == ItemType.NounCategory ) ) {
			//    e.Effect = DragDropEffects.Move;
			//    treeRepository.SelectedNode = tvhti.Node;
			//}
		}

		private void treeRepository_GiveFeedback(object sender, GiveFeedbackEventArgs e)
		{
			if ( _bmpcurDrag != null ) {
				e.UseDefaultCursors = false;
				if ( e.Effect != _bmpcurDrag.Effect ) {
					_bmpcurDrag.Dispose();
					_bmpcurDrag = Helper.CreateDragCursorFromTreeNode(this, e.Effect, _tnDrag);
				}
				if ( Cursor.Current != _bmpcurDrag.Cursor ) {
					Cursor.Current = _bmpcurDrag.Cursor;
				}
			} else {
				e.UseDefaultCursors = true;
			}
		}

		private void treeRepository_ItemDrag(object sender, ItemDragEventArgs e)
		{
			TreeNode tn = e.Item as TreeNode;
			if ( tn == null ) return;

			RepositoryItemBase item = tn.Tag as RepositoryItemBase;
			RepositoryItemBase itemSelected = null;
			if ( treeRepository.SelectedNode != null && treeRepository.SelectedNode.Tag is RepositoryItemBase )
				itemSelected = treeRepository.SelectedNode.Tag as RepositoryItemBase;

			DataObject dataObj = new DataObject();
			if ( item != null ) item.SetDragDropDataObject(dataObj);

			if ( _type == TreeType.DomainEditor ) {
				if ( item == null ) return;

				switch ( item.RepositoryItemType ) {
					case ItemType.Noun:
					//case ItemType.NounCategory:
					case ItemType.BObject:
					case ItemType.Operation:
					case ItemType.Component:
					case ItemType.BPolicy:
					case ItemType.BRule:
					//case ItemType.Domain:
					case ItemType.Composite:
					case ItemType.SOBA:
					case ItemType.SOA:
					case ItemType.Verb:
					case ItemType.WebService:
					case ItemType.HumanActivity:
					case ItemType.Workflow:
					case ItemType.LogicalWebMethod:
					case ItemType.RuleConstant:
						// start drag & drop
						dataObj.SetData(e.Item);
						initDragDropCursor(tn);
						treeRepository.DoDragDrop(dataObj/*e.Item*/,
							DragDropEffects.Move | DragDropEffects.Link | DragDropEffects.Copy);
						break;
					case ItemType.GenericFolder:
						if ( tn.Parent != null && tn.Parent.Tag is GenericFolder ) {
							dataObj.SetData(e.Item);
							initDragDropCursor(tn);
							treeRepository.DoDragDrop(dataObj/*e.Item*/,
								DragDropEffects.Move | DragDropEffects.Link | DragDropEffects.Copy);
						}
						break;
				}
			} else if ( _type == TreeType.ProcessDesigner ) {
				if ( item == null || item.RepositoryItemType != ItemType.Operation ) return;
				// start drag & drop
				dataObj.SetData(e.Item);
				initDragDropCursor(tn);
				treeRepository.DoDragDrop(dataObj/*e.Item*/, DragDropEffects.Move | DragDropEffects.Link);

			}
		}

		private void treeRepository_KeyUp(object sender, KeyEventArgs e)
		{
			if ( e.Control && e.Alt && e.KeyCode == Keys.I ) {
				RepositoryItemBase item = this.treeRepository.SelectedNode.Tag as RepositoryItemBase;
				if ( item != null ) {
					Helpers.OpenDebugViewer(item);
				}
			}
		}

		private void treeRepository_MouseDown(object sender, MouseEventArgs e)
		{
			TreeView tv = sender as TreeView;
			if ( tv == null )
				return;

			if ( e.Button == MouseButtons.Right ) {
				TreeViewHitTestInfo tvhti = tv.HitTest(e.Location);
				tv.SelectedNode = tvhti.Node;
				setContextTreeItems(tvhti);
				contextTreeItems.Show(tv, e.Location, ToolStripDropDownDirection.Default);
			}
		}

		private void treeRepository_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			TreeViewHitTestInfo hti = treeRepository.HitTest(e.Location);
			if ( hti != null &&
				 ( ( hti.Location & TreeViewHitTestLocations.Label ) != TreeViewHitTestLocations.Label &&
				   ( hti.Location & TreeViewHitTestLocations.Image ) != TreeViewHitTestLocations.Image &&
				   ( hti.Location & TreeViewHitTestLocations.StateImage ) != TreeViewHitTestLocations.StateImage )
				 ) return;
			//if ( e.Node != null && !e.Node.Bounds.Contains(e.Location) ) return; // EXIT
			selectItemByTreeNode(e.Node);
		}

		private void treeRepository_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			openDiagramOfCurrentNode();
		}

		private void treeRepository_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
		{
			if ( e.Action != DragAction.Continue ) {
				if ( _tnDrag != null ) {
					_tnDrag.BackColor = treeRepository.BackColor;
					_tnDrag = null;
				}
				if ( _bmpcurDrag != null ) {
					_bmpcurDrag.Dispose();
					_bmpcurDrag = null;
				}
			}
		}

		private void tsbtnRefresh_Click(object sender, EventArgs e)
		{
			using ( new WaitMouse() ) {
				loadRepository();
			}
		}

		private void tsiDomain_Click(object sender, EventArgs e)
		{
			ToolStripItem tsi = sender as ToolStripItem;
			if ( tsi.Tag == null || !( tsi.Tag is int ) ) {
				tsbtnDomain.Text = tsbtnDomain.DropDownItems[0].Text;
				_idDomain = AllDomainsID;
				loadRepository();
			} else {
				if ( tsi.Text.Contains("Domain") )
					tsbtnDomain.Text = tsi.Text;
				else
					tsbtnDomain.Text = string.Format("Domain: {0}", tsi.Text);
				_idDomain = (int)tsi.Tag;
				loadRepository();
			}
		}

		private void tsmiViewBDecisionRules_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewBDecisionRules.Text, ItemType.BPolicy);
		}

		private void tsmiViewBObjects_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewBObjects.Text, ItemType.BObject);
		}

		private void tsmiViewBProcRules_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewBProcRules.Text, ItemType.BPolicy);
		}

		private void tsmiViewBProcesses_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewBProcesses.Text, ItemType.Business_Process);
		}

		private void tsmiViewComposites_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewComposites.Text, ItemType.Composite);
		}

		private void tsmiViewDomains_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewDomains.Text, ItemType.Domain);
		}

		private void tsmiViewHActs_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewHActs.Text, ItemType.HumanActivity);
		}

		private void tsmiViewLogicalMethod_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewLogicalMethod.Text, ItemType.LogicalWebMethod);
		}

		private void tsmiViewMashups_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewMashups.Text, ItemType.Mashup);
		}

		private void tsmiViewOrchestrations_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewOrchestrations.Text, ItemType.Workflow);
		}

		private void tsmiViewRuleConstants_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewRuleConstants.Text, ItemType.RuleConstant);
		}

		private void tsmiViewSelectionRules_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewSelectionRules.Text, ItemType.BPolicy);
		}

		private void tsmiViewVocabulary_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewVocabulary.Text, ItemType.Noun);
		}

		private void tsmiViewWebServices_Click(object sender, EventArgs e)
		{
			setCurrentView(tsmiViewWebServices.Text, ItemType.WebService);
		}

		#endregion Event Handlers

		#region Methods

		private void addBObjectToBObject(TreeNode tnBObj, TreeNode tnSource)
		{
			// TODO: addBObjectToBObject
		}

		private void addDomainIDToRows(DataTable dt)
		{
			dt.Columns.Add("domain_id", typeof(int));
			DataRow[] rows = dt.Select(
				string.Format("parent_reptype_id IS NULL AND child_reptype_id = {0}", (int)ItemType.Domain));
			foreach ( DataRow row in rows ) {
				int domainid = (int)row["child_id"];
				row["domain_id"] = domainid;
				addDomainIDToRowsRecursive(dt, ItemType.Domain, domainid, domainid);
			}
		}

		private void addDomainIDToRowsRecursive(DataTable dt, ItemType currenttype, int currentid, int domainid)
		{
			DataRow[] rows = dt.Select(
				string.Format("parent_reptype_id = {0} AND parent_id = {1}", (int)currenttype, currentid));
			foreach ( DataRow row in rows ) {
				if ( row.IsNull("domain_id") ) {
					row["domain_id"] = domainid;
					ItemType typechild = (ItemType)row["child_reptype_id"];
					if ( typechild == ItemType.Domain )
						addDomainIDToRowsRecursive(dt, typechild, (int)row["child_id"], (int)row["child_id"]);
					else
						addDomainIDToRowsRecursive(dt, typechild, (int)row["child_id"], domainid);
				} else {
					//System.Diagnostics.Debug.WriteLine("Loop");
				}
			}
		}

		private void addNewNodeToCurrentTree(ItemType type, bool bIsRootItem)
		{
			_isInAddNew = true;
			try {
				bool bSaveContinue;
				TreeNode tn;
				TreeNode tnSelected = treeRepository.SelectedNode;

				IRepositoryItem parentItem = null;
				if ( !bIsRootItem && treeRepository.SelectedNode != null )
					parentItem = treeRepository.SelectedNode.Tag as RepositoryItemBase;

				do {
					if ( this.TopLevelControl != null ) this.TopLevelControl.Refresh(); else this.Refresh();
					IRepositoryItem item = this.Repository.GetNewItem(type, true, ref parentItem, out bSaveContinue);//GetItem(type, true, _idRepository, true, out bSaveContinue);
					if ( this.TopLevelControl != null ) this.TopLevelControl.Refresh(); else this.Refresh();
					if ( item == null )
						return;

					if ( !bIsRootItem ) {
						if ( parentItem != null && parentItem is GenericFolder && item is GenericFolder ) {
							( (GenericFolder)item ).ItemTypes = ( (GenericFolder)parentItem ).ItemTypes;
							( (GenericFolder)item ).IsUserFolder = ( (GenericFolder)parentItem ).IsUserFolder;
							item.Save();
						}
					}

					tn = new TreeNode(item.Display);
					tn.Tag = item;
					string keyParent = ( treeRepository.SelectedNode != null ? treeRepository.SelectedNode.Name : "" );
					tn.Name = string.Format("{0}.{1}.{2}", keyParent, (int)item.RepositoryItemType, item.ID);
					tn.ImageKey = item.ImageKey;
					tn.SelectedImageKey = item.SelectedImageKey;

					if ( bIsRootItem ) {
						// add node to tree view
						treeRepository.Nodes.Add(tn);
						treeRepository.SelectedNode = tn;
						// add hierarchy to database
						Global.Data.AddRepositoryHierarchy(null, item, _idRepository);
					} else {
						// add node to parent node
						List<TreeNode> parentNodes = findNodesOfRepositoryItem(parentItem);
						if ( parentNodes.Count > 0 ) {
							foreach ( TreeNode tnParent in parentNodes ) {
								TreeNode tn1 = (TreeNode)tn.Clone();
								tn1.Name = string.Format("{0}.{1}.{2}", tnParent.Name, (int)item.RepositoryItemType, item.ID);
								tn = tn1;
								tnParent.Nodes.Add(tn);
								tnParent.Expand();
							}
						} else {
							if ( tnSelected != null ) {
								tnSelected.Nodes.Add(tn);
								tnSelected.Expand();
							} else {
								treeRepository.SelectedNode.Nodes.Add(tn);
								treeRepository.SelectedNode.Expand();
							}
						}
						// add hierarchy to database
						if ( parentItem == null )
							throw new NullReferenceException("Unknown Repository Tree Node Type.");
						Global.Data.AddRepositoryHierarchy(parentItem, item, _idRepository);
						treeRepository.SelectedNode = tn;
					}
					if ( bIsRootItem ) {
						//loadRepository();
						fillSubTree(tn);
					} else {
						fillSubTree(tn);
					}
					if ( this.TopLevelControl != null ) this.TopLevelControl.Refresh(); else this.Refresh();
				} while ( bSaveContinue );
				onItemSelected(type, tn);
				if ( this.TopLevelControl != null ) this.TopLevelControl.Refresh(); else this.Refresh();
				if ( type == ItemType.Diagram || type == ItemType.BPolicy || type == ItemType.BObject ||
					/*type == ItemType.Composite || */type == ItemType.Component || type == ItemType.SOBA ||
					 type == ItemType.HumanComponent || type == ItemType.SQLComponent ||
					 type == ItemType.Business_Process || type == ItemType.UIComponent ||
					 type == ItemType.Mashup || type == ItemType.Workflow || type == ItemType.System ||
					 type == ItemType.Organization || type == ItemType.Business_Process ) {
					openDiagramOfCurrentNode();
					treeRepository.SelectedNode.Expand();
				}
			} finally {
				_isInAddNew = false;
			}
		}

		private void addNewNodeToCurrentTree(ItemType type, ItemType subtype, bool bIsRootItem)
		{
			_isInAddNew = true;
			try {
				bool bSaveContinue;
				TreeNode tn;
				TreeNode tnSelected = treeRepository.SelectedNode;
				do {
					if ( this.TopLevelControl != null ) this.TopLevelControl.Refresh(); else this.Refresh();
					treeRepository.SelectedNode = tnSelected;
					IRepositoryItem item = this.Repository.GetItem(type, true, _idRepository, true, out bSaveContinue);
					if ( this.TopLevelControl != null ) this.TopLevelControl.Refresh(); else this.Refresh();
					if ( item == null )
						return;

					if ( item is Diagram ) {
						( (Diagram)item ).Type = subtype;
						item.Save();
					}
					tn = new TreeNode(item.Display);
					tn.Tag = item;
					tn.ImageKey = item.ImageKey;
					tn.SelectedImageKey = item.SelectedImageKey;

					if ( bIsRootItem ) {
						// add node to tree view
						treeRepository.Nodes.Add(tn);
						treeRepository.SelectedNode = tn;
						// add hierarchy to database
						Global.Data.AddRepositoryHierarchy(null, item, _idRepository);
					} else {
						// add node to parent node
						treeRepository.SelectedNode.Nodes.Add(tn);
						treeRepository.SelectedNode.Expand();
						// add hierarchy to database
						RepositoryItemBase parentItem = treeRepository.SelectedNode.Tag as RepositoryItemBase;
						if ( parentItem == null )
							throw new NullReferenceException("Unknown Repository Tree Node Type.");
						if ( Global.Data.AddRepositoryHierarchy(parentItem, item, _idRepository) )
							treeRepository.SelectedNode = tn;
					}
					fillSubTree(tn);
				} while ( bSaveContinue );
				onItemSelected(type, tn);
				if ( type == ItemType.Diagram || type == ItemType.BPolicy || type == ItemType.BObject )
					openDiagramOfCurrentNode();
				if ( this.TopLevelControl != null ) this.TopLevelControl.Refresh(); else this.Refresh();
			} finally {
				_isInAddNew = false;
			}
		}

		private void addNounsToBObject(TreeNode tnBObj, TreeNode tnNoun)
		{
			// TODO: addNounsToBObject
		}

		private void addTreeChildNodes(DataTable dtRepository, TreeNodeCollection currentNodesCollection,
			string keyCurrent/*, TreeNode tn, string key*/, IRepositoryItem item)
		{
			// add child tree nodes
			DataRow[] rows;
			if ( item.RepositoryItemType == ItemType.GenericFolder || item.RepositoryItemType == ItemType.Composite ) {
				rows = dtRepository.Select(string.Format(
					"parent_reptype_id = {0} AND parent_id = {1}", (int)item.RepositoryItemType, item.ID),
					"child_display ASC");
			} else {
				rows = dtRepository.Select(string.Format(
					"parent_reptype_id = {0} AND parent_id = {1}", (int)item.RepositoryItemType, item.ID));
			}
			foreach ( DataRow row in rows ) {
				if ( _idDomain > 0 && (int)row["domain_id"] != _idDomain )
					continue;
				//if ( tn != null )
				//    fillTreeRecursive(dtRepository, row, tn.Nodes, key);
				//else
				fillTreeRecursive(dtRepository, row, currentNodesCollection, keyCurrent);
			}
		}

		private bool bobjectContainsItem(TreeNode tnBObj, RepositoryItemBase item)
		{
			bool bContains = false;
			foreach ( TreeNode tn in tnBObj.Nodes ) {
				RepositoryItemBase ri = tn.Tag as RepositoryItemBase;
				if ( ri != null ) {
					if ( ri.RepositoryItemType == item.RepositoryItemType ) {
						if ( ri.ID == item.ID ) {
							bContains = true;
							break;
						}
					}
				}
			}
			return bContains;
		}

		private void deleteCurrentSelectedNode()
		{
			RepositoryItemBase item = treeRepository.SelectedNode.Tag as RepositoryItemBase;
			if ( item == null ) {
				treeRepository.SelectedNode.Remove();
			} else {
				TreeNode tnCurrent = treeRepository.SelectedNode;
				TreeNode tnToSelect = null;
				if ( tnCurrent.PrevNode != null && !( tnCurrent.PrevNode.Tag is Documentation ) ) {
					tnToSelect = tnCurrent.PrevNode;
				} else if ( tnCurrent.NextNode != null ) {
					tnToSelect = tnCurrent.NextNode;
				} else if ( tnCurrent.Parent != null ) {
					tnToSelect = tnCurrent.Parent;
				}
				if ( item.Delete(true) ) {
					if ( tnCurrent != null ) {
						Application.DoEvents();
						tnCurrent.Remove();
					}
					selectItemByTreeNode(tnToSelect);
					if ( tnToSelect != null ) {
						treeRepository.SelectedNode = FindTreeNode(tnToSelect.Tag as IRepositoryItem);
					}
					treeRepository.Refresh();
				}
			}
		}

		private void doRepositoryChanged()
		{
			if ( this.DesignMode )
				return;
			loadRepository();
		}

		private void doTreeTypeChanged()
		{
			if ( this.DesignMode )
				return;
			loadRepository();
		}

		private void fillDomainList()
		{
			while ( tsbtnDomain.DropDownItems.Count > 1 ) {
				tsbtnDomain.DropDownItems.RemoveAt(1);
			}
			DataTable dt = Global.Data.GetRepositoryItemsOfItemType(_idRepository, ItemType.Domain);
			if ( dt == null || dt.Rows.Count == 0 )
				return;

			foreach ( DataRow row in dt.Rows ) {
				ToolStripItem tsi = tsbtnDomain.DropDownItems.Add(
					row["display"].ToString(), null, new EventHandler(this.tsiDomain_Click));
				if ( row["id"] is int )
					tsi.Tag = (int)row["id"];
			}
		}

		private void fillSubTree(TreeNode treenode)
		{
			RepositoryItemBase item = treenode.Tag as RepositoryItemBase;
			if ( item == null )
				return;
			DataTable dt = Global.Data.GetRepositoryHierarchy(_idRepository);
			DataRow[] rows = dt.Select(string.Format(
				"parent_reptype_id = {0} AND parent_id = {1}", (int)item.RepositoryItemType, item.ID));
			treeRepository.BeginUpdate();
			treenode.Nodes.Clear();
			foreach ( DataRow row in rows ) {
				if ( _idDomain > 0 && (int)row["domain_id"] != _idDomain )
					continue;

				fillTreeRecursive(dt, row, treenode.Nodes, treenode.Name);
			}
			treeRepository.EndUpdate();
		}

		private void fillTree()
		{
			_dtRepository = Global.Data.GetRepositoryHierarchy(_idRepository);
			DataRow[] rows;
			List<string> addedItems = new List<string>();

			if ( _typeView == ItemType.Undefined ) {
				rows = _dtRepository.Select("parent_reptype_id IS NULL AND parent_id IS NULL", "parent_display ASC");
			} else if ( _idDomain != UCComponentTree.AllDomainsID ) {
				addDomainIDToRows(_dtRepository);
				rows = _dtRepository.Select(string.Format("child_reptype_id = {0} AND domain_id = {1}", (int)_typeView, _idDomain), "child_display ASC");
			} else {
				rows = _dtRepository.Select(string.Format("child_reptype_id = {0}", (int)_typeView), "child_display ASC");
			}
			foreach ( DataRow row in rows ) {
				if ( _idDomain > 0 && (int)row["domain_id"] != _idDomain ) continue;

				string id = string.Format("{0};{1}", row["child_reptype_id"], row["child_id"]);
				if ( addedItems.Contains(id) )
					continue;
				else
					addedItems.Add(id);

				fillTreeRecursive(_dtRepository, row, treeRepository.Nodes, "");
			}
		}

		private void fillTreeRecursive(DataTable dtRepository, DataRow currentRow,
			TreeNodeCollection currentNodesCollection, string keyCurrent)
		{
			TreeNode tn = null;
			string key = "";
			IRepositoryItem item =
				this.Repository.GetItem((ItemType)currentRow["child_reptype_id"],
										(int)currentRow["child_id"],
										false);

			if ( item == null ) {
				Global.Data.DeleteRepositoryHierarchy((ItemType)currentRow["child_reptype_id"],
										(int)currentRow["child_id"]);
				return;
			}
			RepositoryItemBaseEx itemEx = item as RepositoryItemBaseEx;
			if ( itemEx != null && itemEx.IsDeleted ) {
				Global.Data.DeleteRepositoryHierarchy(itemEx);
				return;
			}
			#region Old Code
			//#if DEBUG
			//if ( itemEx != null ) {
			//    if ( itemEx.DomainId == -1 ) {
			//        if ( currentRow.Table.Columns.Contains("domain_id") )
			//            itemEx.DomainId = currentRow["domain_id"] is int ? (int)currentRow["domain_id"] : -1;
			//        else
			//            itemEx.DomainId = Global.Status.CurrentDomainId;
			//        itemEx.Save();
			//    }
			//}
			//#endif
			#endregion
			if ( _listVisibleTypes.Count == 0 || _listVisibleTypes.Contains((ItemType)currentRow["child_reptype_id"]) ) {
				// create new tree node
				tn = new TreeNode();
				tn.Tag = item;
				string newKeyPart = string.Format(".{0}${1}$", currentRow["child_reptype_id"], currentRow["child_id"]);
				if ( keyCurrent.Contains(newKeyPart) )
					return;

				key = string.Format("{0}{1}", keyCurrent, newKeyPart);
				tn.Name = key;
				// set text
				tn.Text = currentRow["child_display"].ToString();//item.Display;

				// set image keys
				if ( currentRow.IsNull("child_image_key") )
					tn.ImageKey = item.ImageKey;
				else
					tn.ImageKey = currentRow["child_image_key"].ToString();// item.ImageKey;
				if ( currentRow.IsNull("child_selected_image_key") )
					tn.SelectedImageKey = item.SelectedImageKey;
				else
					tn.SelectedImageKey = currentRow["child_selected_image_key"].ToString();// item.SelectedImageKey;
			}
			// add child tree nodes
			DataRow[] rows;
			if ( item.RepositoryItemType == ItemType.GenericFolder ) {
				rows = dtRepository.Select(string.Format(
					"parent_reptype_id = {0} AND parent_id = {1}", (int)item.RepositoryItemType, item.ID),
					"child_display ASC");
			} else {
				rows = dtRepository.Select(string.Format(
					"parent_reptype_id = {0} AND parent_id = {1}", (int)item.RepositoryItemType, item.ID));
			}
			//foreach ( DataRow row in rows ) {
			//    if ( _idDomain > 0 && (int)row["domain_id"] != _idDomain )
			//        continue;
			//    if ( tn != null )
			//        fillTreeRecursive(dtRepository, row, tn.Nodes, key);
			//    else
			//        fillTreeRecursive(dtRepository, row, currentNodesCollection, keyCurrent);
			//}
			if ( rows.Length > 0 )
				tn.Nodes.Add(_LOADING);
			if ( tn != null ) {
				if ( item.RepositoryItemType == ItemType.Documentation ) {
					currentNodesCollection.Insert(0, tn);
				} else {
					currentNodesCollection.Add(tn);
				}
			}
		}

		private List<TreeNode> findNodesOfRepositoryItem(IRepositoryItem item)
		{
			List<TreeNode> listResult = new List<TreeNode>();
			findNodesOfRepositoryItemRecursive(treeRepository.Nodes, item, ref listResult);
			return listResult;
		}

		private void findNodesOfRepositoryItemRecursive(TreeNodeCollection tncCurrent,
			IRepositoryItem item,
			ref List<TreeNode> listResult)
		{
			foreach ( TreeNode tn in tncCurrent ) {
				IRepositoryItem current = tn.Tag as IRepositoryItem;
				if ( current != null && current == item ) {
					listResult.Add(tn);
				} else if ( tn.Nodes.Count > 0 ) {
					findNodesOfRepositoryItemRecursive(tn.Nodes, item, ref listResult);
				}
			}
		}

		private TreeNode findTreeNodeByText(TreeNodeCollection coll, string text)
		{
			TreeNode tnResult = null;
			foreach ( TreeNode tn in coll ) {
				if ( tn.Text == text ) {
					tnResult = tn;
					break;
				}
			}
			return tnResult;
		}

		private TreeNode getParentDomainTreeNode(TreeNode current)
		{
			if ( current.Parent == null ) return null;
			TreeNode domain = current.Parent;
			if ( !( domain.Tag is Domain ) ) domain = getParentDomainTreeNode(current.Parent);
			return domain;
		}

		private int getSelectedDomainID(TreeNode tnSelected)
		{
			if ( tnSelected == null ) return -1;

			return searchParentId(ItemType.Domain, tnSelected);
		}

		private void initDragDropCursor(TreeNode tn)
		{
			_tnDrag = tn;
			tn.BackColor = SystemColors.ControlDark;
			_bmpcurDrag = Helper.CreateDragCursorFromTreeNode(this, DragDropEffects.Move, tn);
		}

		private void loadRepository()
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			if ( this.DesignMode ) return;

			this.UseWaitCursor = true;
			this.Refresh();
			string key = ( treeRepository.SelectedNode != null ? treeRepository.SelectedNode.Name : null );
			treeRepository.SuspendLayout();
			treeRepository.BeginUpdate();
			treeRepository.Tag = repSvc.GetItem(ItemType.Repository, _idRepository, false);
			treeRepository.Nodes.Clear();
			fillDomainList();
			fillTree();
			if ( !string.IsNullOrEmpty(_selectedPath) ) {
				string[] path = _selectedPath.Split(new string[] { treeRepository.PathSeparator }, StringSplitOptions.RemoveEmptyEntries);
				TreeNode tn = null;
				foreach ( string current in path ) {
					tn = findTreeNodeByText(tn == null ? treeRepository.Nodes : tn.Nodes, current);
					if ( tn != null ) {
						tn.Expand();
					}
				}
				treeRepository.SelectedNode = tn;
			}
			if ( key != null && key != "" ) {
				TreeNode[] nodes = treeRepository.Nodes.Find(key, true);
				if ( nodes != null && nodes.Length > 0 )
					treeRepository.SelectedNode = nodes[0];
			}
			treeRepository.EndUpdate();
			treeRepository.ResumeLayout(true);
			this.UseWaitCursor = false;
		}

		private void onCreateProcessForMethod(ItemType type, TreeNode node)
		{
			EventHandler<ItemSelectedEventArgs> tmp = this.CreateProcessForMethod;
			if ( tmp != null )
				tmp(this, new ItemSelectedEventArgs(type, node, _idRepository));
		}

		private void onDeleteItem(ItemType type, TreeNode node)
		{
			EventHandler<ItemSelectedEventArgs> tmp = this.DeleteItem;
			if ( tmp != null )
				tmp(this, new ItemSelectedEventArgs(type, node, _idRepository));
		}

		private void onItemSelected(ItemType type, TreeNode node)
		{
			if ( node == null ) return;
			if ( node.TreeView != null ) {
				// is node was selected before
				if ( _selectedPath == node.FullPath ) return; // EXIT
				try {
					_selectedPath = node.FullPath;
				} catch {
					_selectedPath = "";
				}
			}
			// set current items
			Global.Status.CurrentMainItem = node.Tag as RepositoryItemBase;
			Global.Status.CurrentDomainId = getSelectedDomainID(node);
			// invoke ItemSelected event
			EventHandler<ItemSelectedEventArgs> tmp = this.ItemSelected;
			if ( tmp != null ) {
				int id = _idRepository;
				if ( id > 0 ) tmp(this, new ItemSelectedEventArgs(type, node, id));
			}
		}

		private void openDiagramOfCurrentNode()
		{
			Cursor.Current = Cursors.WaitCursor;
			if ( this.TopLevelControl != null ) this.TopLevelControl.Refresh();
			if ( treeRepository.SelectedNode == null ) return;

			TreeNode selectedNode = treeRepository.SelectedNode;
			RepositoryItemBase item = selectedNode.Tag as RepositoryItemBase;
			if ( item is RepositoryBusinessRule ) {
				selectedNode = selectedNode.Parent;
				item = selectedNode.Tag as RepositoryItemBase;
			}
			if ( item != null ) {
				EventHandler<ItemSelectedEventArgs> tmp = this.OpenDiagram;
				if ( tmp != null )
					tmp(this, new ItemSelectedEventArgs(item.RepositoryItemType, selectedNode, _idRepository));
			}
			Cursor.Current = Cursors.Default;
		}

		//private int getSelectedServiceID()
		//{
		//	if ( treeRepository.SelectedNode == null )
		//		return -1;
		//	return searchParentId(ItemType.Component, treeRepository.SelectedNode);
		//}
		//private int getSelectedVariableID()
		//{
		//	if ( treeRepository.SelectedNode == null )
		//		return -1;
		//	return searchParentId(ItemType.Noun, treeRepository.SelectedNode);
		//}
		private int searchParentId(ItemType type, TreeNode tn)
		{
			int idParent = -1;
			while ( idParent == -1 ) {
				RepositoryItemBase riSel = tn.Tag as RepositoryItemBase;
				if ( riSel != null && riSel.RepositoryItemType == type )
					idParent = riSel.ID;
				else if ( tn.Parent != null )
					tn = tn.Parent;
				else
					idParent = 0;
			}
			return idParent;
		}

		private void selectItemByTreeNode(TreeNode tn)
		{
			RepositoryItemBase item = null;
			if ( tn != null ) item = tn.Tag as RepositoryItemBase;

			if ( item == null ) {
				onItemSelected(ItemType.Undefined, null);
			} else {
				onItemSelected(item.RepositoryItemType, tn);
			}
		}

		private void setContextTreeItems(TreeViewHitTestInfo tvhti)
		{
			RepositoryItemBase item = null;
			GenericFolder folder = null;
			List<ItemType> types = new List<ItemType>();
			if ( tvhti.Node != null ) {
				item = tvhti.Node.Tag as RepositoryItemBase;
				if ( item != null ) {
					folder = item as GenericFolder;
					if ( folder != null ) {
						if ( !folder.IsUserFolder && folder.AllowedChildTypes.Count > 0 ) {
							types.Add(folder.AllowedChildTypes[0]);
						} else {
							types = item.AllowedChildTypes;
						}
					} else {
						types = item.AllowedChildTypes;
					}
				}
				if ( types == null ) {
					types = new List<ItemType>();
				}
				types.Add(ItemType.GenericFolder);
				miTIOpenDiagram.Enabled = true;
				miTIDelete.Enabled = true;
			} else {
				miTIOpenDiagram.Enabled = false;
				miTIDelete.Enabled = false;
			}
			miTIAddChildBObject.Visible = ( types.Contains(ItemType.BObject) );
			miTIAddChildBPolicy.Visible = ( types.Contains(ItemType.BPolicy) );
			miTIAddChildDomain.Visible = ( types.Contains(ItemType.Domain) );
			miTIAddChildNoun.Visible = ( types.Contains(ItemType.Noun) );
			miTIAddChildOperation.Visible = ( types.Contains(ItemType.Operation) );
			miTIAddChildComponent.Visible = ( types.Contains(ItemType.Component) );
			miTIAddChildHumanComponent.Visible = ( types.Contains(ItemType.Component) );
			miTIAddChildUIComponent.Visible = ( types.Contains(ItemType.Component) );
			miTIAddChildSQLComponent.Visible = ( types.Contains(ItemType.Component) );
			miTIAddChildComposite.Visible = ( types.Contains(ItemType.Composite) );
			miTIAddChildVerb.Visible = ( types.Contains(ItemType.Verb) );
			miTIAddChildFolder.Visible = ( types.Contains(ItemType.GenericFolder) );
			miTIAddChildSystem.Visible = ( types.Contains(ItemType.System) );
			miTIAddSOBA.Visible = ( types.Contains(ItemType.SOBA) );
			miTIAddConnectionDiagram.Visible = ( types.Contains(ItemType.Diagram) );
			miTIAddChildBProcess.Visible = ( types.Contains(ItemType.Business_Process) );
			miTIAddChildWorkflow.Visible = ( types.Contains(ItemType.Workflow) );
			miTIAddChildWebService.Visible = ( types.Contains(ItemType.WebService) );
			miTIAddChildMessageQueue.Visible = ( types.Contains(ItemType.MessageQueue) );
			miTIAddChildAPIService.Visible = ( types.Contains(ItemType.WebService) );
			miTIAddChildRuleConstant.Visible = ( types.Contains(ItemType.RuleConstant) );
			miTIAddChildHAForm.Visible = ( types.Contains(ItemType.HumanActivity) );
			miTIAddChildMashup.Visible = ( types.Contains(ItemType.Mashup) );
			miTIAddChildLogMethod.Visible = ( types.Contains(ItemType.LogicalWebMethod) );
			miTIAddChildLogMethodGroup.Visible = ( types.Contains(ItemType.LogicalMethodGroup) );
			miTIAddChildCapability.Visible = ( types.Contains(ItemType.Capability) );
			miTIAddOrg.Visible = ( types.Contains(ItemType.Organization) );

			if ( folder != null ) {
				bool deletable = folder.IsUserFolder ||
					( !( tvhti.Node.Parent.Tag is OpenComposite.EII.Repository.Domain ) &&
					  !( tvhti.Node.Parent.Tag is OpenComposite.EII.Repository.Workflow ) );
				toolStripSeparator6.Visible = deletable;
				miTIDelete.Visible = deletable;
				if ( folder.AllowedChildTypes.Contains(ItemType.BPolicy) ) {
					if ( folder.AllowedChildTypes.Contains(ItemType.Route) ) {
						miTIAddChildBPolicy.Text = "Add Business Process Policy";
					} else if ( folder.AllowedChildTypes.Contains(ItemType.LogicalWebMethod) ) {
						miTIAddChildBPolicy.Text = "Add Selection Policy";
					} else {
						miTIAddChildBPolicy.Text = "Add Business Decision Policy";
					}
				}
			} else {
				bool allowDeleteItem = !( item is Documentation );
#if DEBUG
				// always allow delete in debug version!
				allowDeleteItem = true;
#endif
				toolStripSeparator6.Visible = allowDeleteItem;
				miTIDelete.Visible = allowDeleteItem;
			}
			// hide not used menu items
			if ( item != null ) {
				miTICreateCopy.Visible = !( item.RepositoryItemType == ItemType.GenericFolder ||
											item.RepositoryItemType == ItemType.Domain ||
											item.RepositoryItemType == ItemType.Documentation );
			} else {
				miTICreateCopy.Visible = false;
			}
			if ( tvhti.Node == null ) {
				toolStripSeparator4.Visible = false;
			} else {
				toolStripSeparator4.Visible = true;
			}
		}

		private void setCurrentView(string viewname, ItemType viewtype)
		{
			tsbtnViews.Text = string.Format("View: {0}", viewname);
			_typeView = viewtype;
			loadRepository();
		}

		#endregion Methods

		#endregion Private Members

		#region Other

		//private IRepositoryItem findItemRecursive(IRepositoryItem item)
		//{
		//	List<TreeNode> nodes = findNodesOfRepositoryItem(item);
		//	if(nodes.Count > 0){
		//		nodes[0].Expand();
		//		return item;
		//	}
		//	DataTable dt = Global.Data.GetRepositoryHierarchyParents(item);
		//	if ( dt != null && dt.Rows.Count > 0 ) {
		//		ItemType type = (ItemType)dt.Rows[0]["parent_type_id"];
		//		int parentID = (int)dt.Rows[0]["parent_type_id"];
		//		return Repository.GetItem(type, parentID, false);
		//	}
		//}
		//-----------------------------
		//private void tsmiViewBPolicies_Click(object sender, EventArgs e)
		//{
		//	//setCurrentView(tsmiViewBPolicies.Text, ItemType.BPolicy);
		//}
		//private void tsmiViewSvcComponents_Click(object sender, EventArgs e)
		//{
		//	setCurrentView(tsmiViewComponents.Text, ItemType.Component);
		//}
		//private void tsmiViewSCADiagrams_Click(object sender, EventArgs e)
		//{
		//	//setCurrentView(tsmiViewSCADiagrams.Text, ItemType.Diagram);
		//}
		//private void tsmiViewOrchestrations_Click(object sender, EventArgs e)
		//{
		//	setCurrentView(tsmiViewOrchestrations.Text, ItemType.Workflow);
		//}
		//private void tsmiViewSOBAs_Click(object sender, EventArgs e)
		//{
		//	setCurrentView(tsmiViewSOBAs.Text, ItemType.SOBA);
		//}

		#endregion Other

	}
}